package com.pktechan.api.service.impl;

import com.pktechan.api.entity.TradeOrder;
import com.pktechan.api.enumeration.TradeOrderStatusEnum;
import com.pktechan.api.service.TradeOrderService;
import com.pktechan.api.vo.TradeOrderExpireDelayed;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.CustomizableThreadFactory;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * @program: cloudfloating
 * @description: 项目启动时执行订单过期延迟队列执行
 * @author: qx.zhang
 * @create: 2021-04-14 16:59
 **/
@Component
public class TradeOrderExpireRunnerImpl {

    private static final Logger logger = LoggerFactory.getLogger(TradeOrderExpireRunnerImpl.class);
    @Autowired
    private TradeOrderService tradeOrderService;

    @Autowired
    DelayQueue tradeOrderExpireDelayedQueue;

    private static AtomicBoolean start = new AtomicBoolean(false);
    // 线程池
    private static ThreadFactory threadFactory = new CustomizableThreadFactory("orderExpireDelayedThreadFactory");

    private static ExecutorService executorService = new ThreadPoolExecutor(
            3, // 核心线程池大小
            6, // 最大线程池大小
            60L, // 线程最大空闲时间
            TimeUnit.MILLISECONDS, // 时间单位(毫秒)
            new LinkedBlockingQueue<Runnable>(),  // 线程等待队列
            threadFactory, // 线程创建工厂
            new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
    );

    public <T> void start() {
        if (start.get()) {
            return;
        }
        start.set(true);

        executorService.submit(() -> {
            // 取消订单
            while (start.get()) {
                try {
                    TradeOrderExpireDelayed tradeOrderExpireDelayed = (TradeOrderExpireDelayed) tradeOrderExpireDelayedQueue.take();
                    logger.debug("订单编号：" + tradeOrderExpireDelayed.getTradeOrderId() + " 过期时间：" + tradeOrderExpireDelayed.getExpirationTime());
                    //首先查询订单是否支付，如果支付移除此延时
                    TradeOrder tradeOrder = tradeOrderService.getById(tradeOrderExpireDelayed.getTradeOrderId());
                    if (TradeOrderStatusEnum.TO_BE_PAID.getCode().equals(tradeOrder.getStatus())) {
                        tradeOrder.setId(tradeOrderExpireDelayed.getTradeOrderId());
                        tradeOrder.setStatus(TradeOrderStatusEnum.CLOSED.getCode());
                        tradeOrderService.update(tradeOrder);
                        logger.debug("订单已执行过期操作，订单ID：" + tradeOrder.getId());
                    } else {
                        logger.debug("订单非待付款状态，删除此延时队列。订单ID：" + tradeOrder.getId());
                        tradeOrderExpireDelayedQueue.remove(tradeOrderExpireDelayed);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    logger.debug("执行过期失败了。");
                }
            }
        });
    }

    @PostConstruct
    public void tradeOrderExpireRun() throws Exception {
        logger.debug("通过实现ApplicationRunner接口，在spring boot项目启动后执行");
        List<TradeOrderExpireDelayed> tradeOrderExpireDelayedList = tradeOrderService.getTradeOrderExpireList();
        for (TradeOrderExpireDelayed tradeOrderExpireDelayed : tradeOrderExpireDelayedList) {
            tradeOrderExpireDelayedQueue.add(tradeOrderExpireDelayed);
        }
        logger.debug("延时队列实现订单过期");
        start();
    }
}
